﻿using System;
using System.Drawing;
using System.Windows.Forms;

namespace Useful.GUI.HierarchyDataGridView
{
    public class DataGridViewColumn2LevelHeaderCell : DataGridViewColumnHeaderCell
    {
        private readonly string mainHeader;
        private readonly int columnSpan;
        private bool isChecked;
        private Rectangle cbRect = new Rectangle(20, 0, 20, 20);
        private readonly Font mainHeaderFont = null;

        private int MainHeight { get; set; }
        private int SubHeight { get; set; }

        public bool Checked
        {
            get
            {
                return isChecked;
            }
        }

        public int ColumnSpan
        {
            get
            {
                return columnSpan;
            }
        }

        public DataGridViewColumn2LevelHeaderCell(string mainHeader, int columnSpan, Font font, int mainHeight, int subHeight)
        {
            this.mainHeader = mainHeader;
            this.columnSpan = columnSpan;
            this.mainHeaderFont = font;
            this.MainHeight = mainHeight;
            this.SubHeight = subHeight;
        }

        public DataGridViewColumn2LevelHeaderCell(string mainHeader, int columnSpan, Font font)
            : this(mainHeader, columnSpan, font, -1, -1)
        {
        }

        public DataGridViewColumn2LevelHeaderCell(string mainHeader, int columnSpan)
            : this(mainHeader, columnSpan, null)
        {
        }

        public DataGridViewColumn2LevelHeaderCell(string mainHeader, int columnSpan, int mainHeight, int subHeight)
            : this(mainHeader, columnSpan, null, mainHeight, subHeight)
        {
        }

        public int GetHeight(int h)
        {
            if (MainHeight != -1)
                return MainHeight;
            else if (SubHeight != -1)
                return h - SubHeight;
            else
                return h / 2;
        }

        protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates dataGridViewElementState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
        {
            System.Diagnostics.Debug.WriteLine(String.Format("DataGridViewColumn2LevelHeaderCell.Paint - rowIndex = {0}, ColumnIndex = {1}, colName = {2}, cellBounds = {3}", rowIndex, ColumnIndex, DataGridView.Columns[ColumnIndex].Name, cellBounds));

            if (isChecked)
                cellStyle.BackColor = Color.LightBlue;

            int width = GetWidth();
            int height = GetHeight(cellBounds.Height);

            Rectangle rect1 = new Rectangle(cellBounds.X, cellBounds.Y, width, height);
            Rectangle rect2 = new Rectangle(cellBounds.X, cellBounds.Y + height, cellBounds.Width, cellBounds.Height - height);

            graphics.FillRectangle(new SolidBrush(InheritedStyle.BackColor), rect1);

            base.Paint(graphics, clipBounds, rect2, rowIndex, dataGridViewElementState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts);
        }

        private TextFormatFlags CellStyleAligmentToTextFormatFlags(DataGridViewContentAlignment aligment)
        {
            TextFormatFlags flags = TextFormatFlags.Default;

            switch (aligment)
            {
                case DataGridViewContentAlignment.BottomCenter:
                    flags = TextFormatFlags.Bottom | TextFormatFlags.HorizontalCenter;
                    break;
                case DataGridViewContentAlignment.BottomLeft:
                    flags = TextFormatFlags.Bottom | TextFormatFlags.Left;
                    break;
                case DataGridViewContentAlignment.BottomRight:
                    flags = TextFormatFlags.Bottom | TextFormatFlags.Right;
                    break;
                case DataGridViewContentAlignment.MiddleCenter:
                    flags = TextFormatFlags.VerticalCenter | TextFormatFlags.HorizontalCenter;
                    break;
                case DataGridViewContentAlignment.MiddleLeft:
                    flags = TextFormatFlags.VerticalCenter | TextFormatFlags.Left;
                    break;
                case DataGridViewContentAlignment.MiddleRight:
                    flags = TextFormatFlags.VerticalCenter | TextFormatFlags.Right;
                    break;
                case DataGridViewContentAlignment.TopCenter:
                    flags = TextFormatFlags.Top | TextFormatFlags.HorizontalCenter;
                    break;
                case DataGridViewContentAlignment.TopLeft:
                    flags = TextFormatFlags.Top | TextFormatFlags.Left;
                    break;
                case DataGridViewContentAlignment.TopRight:
                    flags = TextFormatFlags.Top | TextFormatFlags.Right;
                    break;
            }

            return flags;
        }

        public void DrawCell(Graphics graphics, Rectangle rect1)
        {
            graphics.FillRectangle(new SolidBrush(InheritedStyle.BackColor), rect1);

            TextFormatFlags flags = CellStyleAligmentToTextFormatFlags(this.Style.Alignment);

            TextRenderer.DrawText(graphics, mainHeader, (mainHeaderFont ?? InheritedStyle.Font), rect1, InheritedStyle.ForeColor, InheritedStyle.BackColor,
                flags |
                TextFormatFlags.PreserveGraphicsClipping | TextFormatFlags.WordBreak
            );

            graphics.DrawLine(Pens.Black, rect1.Right - 2, rect1.Top, rect1.Right - 2, rect1.Bottom);
        }

        public bool IsMouseInCell(Point p)
        {
            Rectangle rect1 = DataGridView.GetCellDisplayRectangle(ColumnIndex, RowIndex, false);

            int height = GetHeight(rect1.Height);

            Rectangle rect2 = new Rectangle(new Point(rect1.X + cbRect.X, rect1.Y + height + cbRect.Y), cbRect.Size);

            return !rect2.Contains(p);
        }

        public void ProcessCheck()
        {
            isChecked = !isChecked;
        }

        public int GetWidth()
        {
            int width = 0;

            for (int i = 0; i < columnSpan; i++)
            {
                width += DataGridView.Columns[ColumnIndex + i].Width;
            }

            return width;
        }
    }
}
